<script lang="ts" setup>
import type {
  TooltipComponentOption,
  GridComponentOption,
  GraphicComponentOption,
  LineSeriesOption,
  ComposeOption,
  DefaultLabelFormatterCallbackParams,
  LegendComponentOption,
  ToolboxComponentOption,
} from 'echarts';

import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import { TooltipComponent, GridComponent, GraphicComponent, LegendComponent, ToolboxComponent } from 'echarts/components';
import { SVGRenderer } from 'echarts/renderers';
import { UniversalTransition } from 'echarts/features';
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import { $fetch } from '@/settings/utils/fetch';
import { useI18n } from 'vue-i18n';

const { t } = useI18n();
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = ComposeOption<
  | LineSeriesOption
  | TooltipComponentOption
  | GridComponentOption
  | GraphicComponentOption
  | LegendComponentOption
  | ToolboxComponentOption
>;

// 注册必须的组件
echarts.use([
  TooltipComponent,
  GridComponent,
  GraphicComponent,
  LineChart,
  SVGRenderer,
  UniversalTransition,
  LegendComponent,
  ToolboxComponent,
]);

export interface AnyObject {
  [key: string]: unknown;
}

export interface ToolTipFormatterCallbackParams extends DefaultLabelFormatterCallbackParams {
  axisDim: string;
  axisIndex: number;
  axisType: string;
  axisId: string;
  axisValue: string;
  axisValueLabel: string;
}

const chartEl = ref();
const loading = ref(false);
const xAxis = ref<string[]>([]);
const chartsData = ref<number[]>([]);
const detail = ref<Record<string, any>>({});

const graphicFactory = (side: AnyObject) => {
  return {
    type: 'text',
    bottom: '8',
    ...side,
    style: {
      text: '',
      textAlign: 'center',
      fill: '#4E5969',
      fontSize: 12,
    },
  };
};

const graphicElements = ref([
  graphicFactory({ left: '2.6%' }),
  graphicFactory({ right: 0 }),
]);

const option: ECOption = {
  grid: {
    left: '2.6%',
    right: '2.6%',
    top: '30',
    bottom: '30',
  },
  legend: {
    data: ['PV'],
  },
  toolbox: {
    feature: {
      saveAsImage: {
        show: true,
        title: t('settings.view.welcome.save'),
      },
    },
  },
  xAxis: {
    type: 'category',
    offset: 2,
    boundaryGap: false,
    axisLabel: {
      color: '#4E5969',
      rich: {
        today: {
          color: '#2d2d2d',
          fontWeight: 'bold',
        },
      },
    },
    axisLine: {
      show: false,
    },
    axisTick: {
      show: false,
    },
    splitLine: {
      show: true,
      lineStyle: {
        color: '#E5E8EF',
      },
    },
    axisPointer: {
      show: true,
      lineStyle: {
        color: '#23ADFF',
        width: 2,
      },
    },
  },
  yAxis: {
    type: 'value',
    axisLine: {
      show: false,
    },
    minInterval: 1,
    splitLine: {
      show: true,
      lineStyle: {
        type: 'dashed',
        color: '#E5E8EF',
      },
    },
  },
  tooltip: {
    trigger: 'axis',
    formatter(params) {
      const [firstElement] = params as ToolTipFormatterCallbackParams[];
      return `<div>
<p class="tooltip-title">${firstElement.axisValueLabel}:00</p>
<div class="content-panel"><span>PV</span><span class="tooltip-value">${firstElement.value}</span></div>
</div>`;
    },
    className: 'echarts-tooltip-diy',
  },
  graphic: {
    elements: graphicElements.value,
  },
  series: [
    {
      name: 'PV',
      data: [],
      type: 'line',
      smooth: true,
      symbolSize: 12,
      emphasis: {
        focus: 'series',
        itemStyle: {
          borderWidth: 2,
        },
      },
      lineStyle: {
        width: 3,
        color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
          {
            offset: 0,
            color: 'rgba(30, 231, 255, 1)',
          },
          {
            offset: 0.5,
            color: 'rgba(36, 154, 255, 1)',
          },
          {
            offset: 1,
            color: 'rgba(111, 66, 251, 1)',
          },
        ]),
      },
      showSymbol: false,
      areaStyle: {
        opacity: 0.8,
        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
          {
            offset: 0,
            color: 'rgba(17, 126, 255, 0.16)',
          },
          {
            offset: 1,
            color: 'rgba(17, 128, 255, 0)',
          },
        ]),
      },
    },
  ],
};

let chartInstance: echarts.ECharts;

const refresh = async () => {
  const { isSuccess, data } = await $fetch('/admin/record/today', {
    loadingStatus: loading,
  });

  if (isSuccess) {
    detail.value = data;
    xAxis.value = [];
    chartsData.value = [];

    for (let i = 0; i < 24; i++) {
      xAxis.value.push(String(i));
      chartsData.value.push(data.pvDetailRecord.find((item: Record<string, number>) => {
        if (item.x == i) {
          return true;
        }
      })?.y ?? 0);
    }

    chartInstance.setOption({
      xAxis: {
        data: xAxis.value,
        splitLine: {
          interval: (idx: number) => {
            if (idx === 0) { return false; }
            if (idx === xAxis.value.length - 1) { return false; }
            return true;
          },
        },
      },
      series: [{
        data: chartsData.value,
      }],
    });
  }
}

onMounted(async () => {
  await nextTick();

  chartInstance = echarts.init(chartEl.value, null, { renderer: 'svg' });
  chartInstance.setOption(option);

  refresh();

  if (window.ResizeObserver) {
    const resizeObserver = new ResizeObserver(() => {
      chartInstance.resize();
    });

    resizeObserver.observe(chartEl.value);
  }
});

onUnmounted(() => {
  chartInstance?.dispose();
});
</script>

<template>
  <ASpin :loading="loading" class="content-chart w-full">
    <OpenGeneralCard :title="$t('settings.view.welcome.overview.title')">
      <AGrid :cols="24" :row-gap="16" :col-gap="16">
        <AGridItem :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 12 }">
          <div ref="chartEl" class="h-289px w-full"></div>
        </AGridItem>
        <AGridItem :span="{ xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 12 }">
          <div class="flex-x-center">
            <AGrid :cols="24" :row-gap="16" class="w-full">
              <AGridItem :span="12" class="h-100 flex-center b-r-1 b-r-gray-2">
                <AStatistic :title="$t('settings.view.welcome.overview.pv')" :value="detail.pv ?? 0" :value-from="0" animation show-group-separator />
              </AGridItem>
              <AGridItem :span="12" class="h-100 flex-center">
                <AStatistic :title="$t('settings.view.welcome.overview.user')" :value="detail.active ?? 0" :value-from="0" animation show-group-separator />
              </AGridItem>
              <AGridItem :span="12" class="h-100 flex-center b-r-1 b-r-gray-2">
                <AStatistic :title="$t('settings.view.welcome.overview.repository')" :value="detail.newWarehouse ?? 0" :value-from="0" animation show-group-separator />
              </AGridItem>
              <AGridItem :span="12" class="h-100 flex-center">
                <AStatistic :title="$t('settings.view.welcome.overview.organization')" :value="detail.newOrg ?? 0" :value-from="0" animation show-group-separator />
              </AGridItem>
            </AGrid>
          </div>
        </AGridItem>
      </AGrid>
    </OpenGeneralCard>
  </ASpin>
</template>

<style lang="scss" scoped>
.content-chart {
  :deep() {
    .echarts-tooltip-diy {
      background: linear-gradient(304.17deg, rgba(253, 254, 255, 0.6) -6.04%, rgba(244, 247, 252, 0.6) 85.2%) !important;
      border: none !important;
      border-radius: 6px !important;
      backdrop-filter: blur(10px) !important;

      .content-panel {
        display: flex;
        justify-content: space-between;
        width: 164px;
        height: 32px;
        margin-bottom: 4px;
        padding: 0 9px;
        line-height: 32px;
        background: rgba(255, 255, 255, 0.8);
        border-radius: 4px;
        box-shadow: 6px 0 20px rgba(34, 87, 188, 0.1);
      }

      .tooltip-title {
        margin: 0 0 10px 0;
      }

      p {
        margin: 0;
      }

      .tooltip-title,
      .tooltip-value {
        display: flex;
        align-items: center;
        color: #1d2129;
        font-weight: bold;
        font-size: 13px;
        line-height: 15px;
        text-align: right;
      }

      .tooltip-item-icon {
        display: inline-block;
        width: 10px;
        height: 10px;
        margin-right: 8px;
        border-radius: 50%;
      }
    }
  }
}
</style>
